package net.lastcoder.ifserver.command;

import net.lastcoder.ifserver.Server;
import net.lastcoder.ifserver.plugin.Plugin;
import net.lastcoder.ifserver.plugin.PluginManager;
import net.lastcoder.ifserver.script.ScriptManage;
import net.lastcoder.ifserver.util.StringUtils;
import net.lastcoder.ifserver.util.TextUtils;

import org.apache.log4j.Level;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;

/**
 * auth: WenYF
 * date: 2016/11/28
 */
public class DefaultCommandProvider implements CommandProvider {
    private PluginManager pluginManager;
    
    private int SHUTDOWN_TIMEOUT = 10000;
    private long requestShutdownTime = 0;
    public DefaultCommandProvider() {
        pluginManager = Server.getInstance().getPluginManager();
    }

    @Override
    public String processCommand(String com) {
        // 处理命令
        String ret = "not this command";
        StringTokenizer st = new StringTokenizer(com, " ");
        StringBuilder sb = new StringBuilder();
        while(st.hasMoreTokens()) {
            String str = next(st);
            if ("shutdown".equalsIgnoreCase(str)) {
                if (System.currentTimeMillis() - requestShutdownTime > SHUTDOWN_TIMEOUT) {
                    // 10内再次输入 shutdown 关闭
                    ret = "input 'shutdown' again within  " + (SHUTDOWN_TIMEOUT / 1000) 
                            + " seconds to shutdown server.";
                } else {
                    System.exit(0); // invokes shutdown hook(s)
                }
                requestShutdownTime = System.currentTimeMillis();
            } else if ("show".equalsIgnoreCase(str)) {
                str = next(st);

                if ("plugins".equalsIgnoreCase(str)) {
                    for (Plugin plugin : pluginManager.getPlugins()) {
                        sb.append("name=").append(pluginManager.getName(plugin));
                        sb.append(" Author=").append(pluginManager.getAuthor(plugin));
                        sb.append(" version=").append(pluginManager.getVersion(plugin));
                        sb.append(" desc=").append(pluginManager.getDescription(plugin)).append("\n");
                    }

                    ret = sb.toString();
                    if (TextUtils.isEmpty(ret)) {
                        ret = "no plugins";
                    }
                } else if ("thread".equalsIgnoreCase(str)) {
                    ret = "thread count:" + Thread.activeCount() + "";
                } else if ("memory".equalsIgnoreCase(str)) {
                    long take = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
                    take = take / 1024 / 1024;
                    long free = Runtime.getRuntime().freeMemory() / 1024 / 1024;
                    long max = Runtime.getRuntime().maxMemory() / 1024 / 1024;
                    long total = Runtime.getRuntime().totalMemory() / 1024 / 1024;
                    ret = "current:" + take + "m/" + total  + "m\t" + "max:" + max + "m";

                } else if ("info".equalsIgnoreCase(str)) {
                    Runtime r = Runtime.getRuntime();
                    Properties props = System.getProperties();
                    InetAddress addr = null;
                    String ip = null;
                    try {
                        addr = InetAddress.getLocalHost();
                        ip = addr.getHostAddress();
                    } catch (UnknownHostException e) {
                        e.printStackTrace();
                    }

                    Map<String, String> map = System.getenv();
                    String userName = map.get("USERNAME");// 获取用户名
                    String computerName = map.get("COMPUTERNAME");// 获取计算机名
                    String userDomain = map.get("USERDOMAIN");// 获取计算机域名
                    assemble(sb, "用户名:    " + userName);
                    assemble(sb, "计算机名:   " + computerName);
                    assemble(sb, "计算机域名:  " + userDomain);
                    assemble(sb, "本地ip地址: " + ip);
                    assemble(sb, "本地主机名:  " + addr.getHostName());
                    assemble(sb, "JVM可以使用的总内存:    " + r.totalMemory());
                    assemble(sb, "JVM可以使用的剩余内存:   " + r.freeMemory());
                    assemble(sb, "JVM可以使用的处理器个数:  " + r.availableProcessors());
                    assemble(sb, "Java的运行环境版本：    " + props.getProperty("java.version"));
                    assemble(sb, "Java的运行环境供应商：   " + props.getProperty("java.vendor"));
                    assemble(sb, "Java供应商的URL：    " + props.getProperty("java.vendor.url"));
                    assemble(sb, "Java的安装路径：  " + props.getProperty("java.home"));
                    assemble(sb, "Java的虚拟机规范版本：   " + props.getProperty("java.vm.specification.version"));
                    assemble(sb, "Java的虚拟机规范供应商：  " + props.getProperty("java.vm.specification.vendor"));
                    assemble(sb, "Java的虚拟机规范名称：   " + props.getProperty("java.vm.specification.name"));
                    assemble(sb, "Java的虚拟机实现版本：   " + props.getProperty("java.vm.version"));
                    assemble(sb, "Java的虚拟机实现供应商：  " + props.getProperty("java.vm.vendor"));
                    assemble(sb, "Java的虚拟机实现名称：   " + props.getProperty("java.vm.name"));
                    assemble(sb, "Java运行时环境规范版本：  " + props.getProperty("java.specification.version"));
                    assemble(sb, "Java运行时环境规范供应商： " + props.getProperty("java.specification.vender"));
                    assemble(sb, "Java运行时环境规范名称：  " + props.getProperty("java.specification.name"));
                    assemble(sb, "Java的类格式版本号：    " + props.getProperty("java.class.version"));
                    assemble(sb, "Java的类路径：   " + props.getProperty("java.class.path"));
                    assemble(sb, "加载库时搜索的路径列表：    " + props.getProperty("java.library.path"));
                    assemble(sb, "默认的临时文件路径：  " + props.getProperty("java.io.tmpdir"));
                    assemble(sb, "一个或多个扩展目录的路径：   " + props.getProperty("java.ext.dirs"));
                    assemble(sb, "操作系统的名称：    " + props.getProperty("os.name"));
                    assemble(sb, "操作系统的构架：    " + props.getProperty("os.arch"));
                    assemble(sb, "操作系统的版本：    " + props.getProperty("os.version"));
                    assemble(sb, "文件分隔符：  " + props.getProperty("file.separator"));
                    assemble(sb, "路径分隔符：  " + props.getProperty("path.separator"));
                    assemble(sb, "行分隔符：   " + props.getProperty("line.separator"));
                    assemble(sb, "用户的账户名称：    " + props.getProperty("user.name"));
                    assemble(sb, "用户的主目录： " + props.getProperty("user.home"));
                    assemble(sb, "用户的当前工作目录：  " + props.getProperty("user.dir"));

                    ret = sb.toString();
                }
            } else if ("set".equalsIgnoreCase(str)) {
                str = next(st);
                if ("log".equalsIgnoreCase(str)) {
                    str = next(st);
                    org.apache.log4j.LogManager.getRootLogger().setLevel(Level.toLevel(str));
                    ret = "ok";
                }
            } else if ("call".equalsIgnoreCase(str)) {
                str = next(st);
                if ("gc".equalsIgnoreCase(str)) {
                    System.gc();
                    ret = "ok";
                }
            } else if ("delete".equalsIgnoreCase(str)) {
                str = next(st);

                if ("plugin".equalsIgnoreCase(str)) {
                    str = nextRemain(st);

                    if (TextUtils.isEmpty(str)) {
                        return "input error.";
                    }
                    
                    Server.getInstance().getPluginManager().unloadPlugin(str);
                }

                ret = "ok";
            } else if ("reload".equalsIgnoreCase(str)) {
                str = next(st);
                if ("script".equalsIgnoreCase(str)) {
                    ScriptManage.getInstance().reload();
                    System.gc();
                }

                ret = "ok";
            }
        }

        return ret + "\n";
    }

    protected String next(StringTokenizer st) {
        if (st.hasMoreTokens()) {
            String str = st.nextToken();
            //System.out.println("str = " + str);
            return str;
        } else {
            return "";
        }
    }

    protected String nextRemain(StringTokenizer st) {
        String str = "";
        while (st.hasMoreTokens()) {
            str = str + " " + st.nextToken();
        }
        return str.trim();
    }

    protected StringBuilder assemble(StringBuilder sb, String str) {
        sb.append(str).append("\n");
        return sb;
    }
}
